import axios, { AxiosInstance, AxiosResponse } from 'axios'
import { AIRequest, AIResponse, APIConfig, NetworkError, PlayRequest, PlayResponse, PlayActionItem } from '../types/api'
import { GameState } from '../types/game'
import { convertCardsToAPIIds } from '../utils/cardUtils'
import { CardPattern } from '../types/card'
import qs from 'qs';

/**
 * AI服务类
 */
class AIService {
  private client: AxiosInstance
  private config: APIConfig

  constructor(config?: Partial<APIConfig>) {
    this.config = {
      baseURL: import.meta.env.VITE_API_BASE_URL || 'https://ai-guandan-test.duole.com', // 从环境变量读取API地址
      timeout: 30000, // 30秒超时
      retryCount: 3,
      ...config
    }

    this.client = axios.create({
      baseURL: this.config.baseURL,
      timeout: this.config.timeout,
      headers: {
        'Content-Type': 'application/x-www-form-urlencoded',
      }
    })

    this.setupInterceptors()
  }


  /**
   * 设置请求和响应拦截器
   */
  private setupInterceptors() {
    // 请求拦截器
    this.client.interceptors.request.use(
      (config) => {
        console.log('AI API 请求:', {
          url: config.url,
          method: config.method,
          data: config.data
        })
        return config
      },
      (error) => {
        console.error('AI API 请求错误:', error)
        return Promise.reject(error)
      }
    )

    // 响应拦截器
    this.client.interceptors.response.use(
      (response: AxiosResponse<AIResponse>) => {
        console.log('AI API 响应:', {
          status: response.status,
          data: response.data
        })
        return response
      },
      (error) => {
        console.error('AI API 响应错误:', error)

        const networkError: NetworkError = {
          code: error.code || 'UNKNOWN_ERROR',
          message: error.message || '网络请求失败',
          status: error.response?.status
        }

        return Promise.reject(networkError)
      }
    )
  }

  /**
   * 构建AI请求数据
   */
  private buildAIRequest(gameState: GameState): AIRequest {
    const request: AIRequest = {
      gameState: {
        players: gameState.players.map(player => ({
          seatid: player.id,
          cards: convertCardsToAPIIds(player.handCards),
          patterntype: player.currentPlay.length > 0 ? 1 : 0 // 简化的牌型，实际应该识别具体牌型
        })),
        currentRound: gameState.currentRound,
        lastPlay: gameState.lastPlay ? convertCardsToAPIIds(gameState.lastPlay.cards) : [],
        trumpCard: gameState.config.trumpCard ? gameState.config.trumpCard.id : null
      },
      aiCards: convertCardsToAPIIds(gameState.config.aiCards)
    }

    return request
  }

  /**
   * 调用AI决策接口
   */
  async getAIDecision(gameState: GameState): Promise<AIResponse> {
    try {
      const request = this.buildAIRequest(gameState)

      console.log('发送AI请求:', request)

      const response = await this.client.post<AIResponse>('/ai/decision', request)

      if (!response.data.success) {
        throw new Error(response.data.message || 'AI决策失败')
      }

      return response.data
    } catch (error) {
      console.error('AI决策请求失败:', error)
      throw this.handleError(error)
    }
  }

  /**
   * 带重试的AI决策调用
   */
  async getAIDecisionWithRetry(gameState: GameState): Promise<AIResponse> {
    let lastError: Error | null = null

    for (let attempt = 1; attempt <= this.config.retryCount; attempt++) {
      try {
        console.log(`AI决策请求尝试 ${attempt}/${this.config.retryCount}`)

        const result = await this.getAIDecision(gameState)

        console.log(`AI决策请求成功 (尝试 ${attempt})`)
        return result

      } catch (error) {
        lastError = error as Error
        console.warn(`AI决策请求失败 (尝试 ${attempt}/${this.config.retryCount}):`, error)

        // 如果不是最后一次尝试，等待一段时间后重试
        if (attempt < this.config.retryCount) {
          const delay = Math.min(1000 * Math.pow(2, attempt - 1), 5000) // 指数退避，最大5秒
          console.log(`等待 ${delay}ms 后重试...`)
          await this.sleep(delay)
        }
      }
    }

    throw lastError || new Error('AI决策请求失败')
  }

  /**
   * 测试AI服务连接
   */
  async testConnection(): Promise<boolean> {
    try {
      const response = await this.client.get('/health')
      return response.status === 200
    } catch (error) {
      console.error('AI服务连接测试失败:', error)
      return false
    }
  }

  /**
   * 获取AI服务状态
   */
  async getServiceStatus(): Promise<{
    online: boolean
    version?: string
    uptime?: number
  }> {
    try {
      const response = await this.client.get('/status')
      return {
        online: true,
        version: response.data.version,
        uptime: response.data.uptime
      }
    } catch (error) {
      return { online: false }
    }
  }

  /**
   * 调用出牌接口
   */
  async playCard(request: PlayRequest): Promise<PlayResponse> {
    try {
      const payload = {
        params: JSON.stringify(request)
      }
      const response = await this.client.post<PlayResponse>('/play', qs.stringify(payload))

      console.log('出牌响应:', response.data)

      if (response.data.code !== 0) {
        throw new Error(`出牌接口返回错误码: ${response.data.code}`)
      }

      return response.data
    } catch (error) {
      console.error('出牌请求失败:', error)
      throw this.handleError(error)
    }
  }

  /**
   * 带重试的出牌接口调用
   */
  async playCardWithRetry(request: PlayRequest): Promise<PlayResponse> {
    let lastError: Error | null = null

    for (let attempt = 1; attempt <= this.config.retryCount; attempt++) {
      try {
        console.log(`出牌请求尝试 ${attempt}/${this.config.retryCount}`)

        const result = await this.playCard(request)

        console.log(`出牌请求成功 (尝试 ${attempt})`)
        return result

      } catch (error) {
        lastError = error as Error
        console.warn(`出牌请求失败 (尝试 ${attempt}/${this.config.retryCount}):`, error)

        // 如果不是最后一次尝试，等待一段时间后重试
        if (attempt < this.config.retryCount) {
          const delay = Math.min(1000 * Math.pow(2, attempt - 1), 5000)
          console.log(`等待 ${delay}ms 后重试...`)
          await this.sleep(delay)
        }
      }
    }

    throw lastError || new Error('出牌请求失败')
  }

  /**
   * 更新配置
   */
  updateConfig(newConfig: Partial<APIConfig>) {
    this.config = { ...this.config, ...newConfig }

    // 重新创建axios实例
    this.client = axios.create({
      baseURL: this.config.baseURL,
      timeout: this.config.timeout,
      headers: {
        'Content-Type': 'application/x-www-form-urlencoded',
      }
    })

    this.setupInterceptors()
  }

  /**
   * 错误处理
   */
  private handleError(error: any): Error {
    if (error.code === 'ECONNREFUSED') {
      return new Error('无法连接到AI服务，请检查服务是否启动')
    }

    if (error.code === 'ENOTFOUND') {
      return new Error('AI服务地址无法解析，请检查网络连接')
    }

    if (error.code === 'ETIMEDOUT') {
      return new Error('AI服务请求超时，请稍后重试')
    }

    if (error.status === 400) {
      return new Error('请求参数错误')
    }

    if (error.status === 500) {
      return new Error('AI服务内部错误')
    }

    return error instanceof Error ? error : new Error('未知错误')
  }

  /**
   * 延时工具函数
   */
  private sleep(ms: number): Promise<void> {
    return new Promise(resolve => setTimeout(resolve, ms))
  }
}

// 创建默认AI服务实例
const aiService = new AIService()

/**
 * 获取AI决策
 */
export async function getAIDecision(gameState: GameState): Promise<AIResponse> {
  return aiService.getAIDecisionWithRetry(gameState)
}

/**
 * 测试AI服务连接
 */
export async function testAIConnection(): Promise<boolean> {
  return aiService.testConnection()
}

/**
 * 获取AI服务状态
 */
export async function getAIServiceStatus() {
  return aiService.getServiceStatus()
}

/**
 * 配置AI服务
 */
export function configureAIService(config: Partial<APIConfig>) {
  aiService.updateConfig(config)
}

/**
 * 调用出牌接口
 */
export async function playCard(request: PlayRequest): Promise<PlayResponse> {
  return aiService.playCardWithRetry(request)
}

/**
 * 根据游戏状态构建出牌请求
 */
export function buildPlayRequest(
  gameState: GameState,
  playerId: number,
  recordId: string = 'default-record-id'
): PlayRequest {
  const player = gameState.players.find(p => p.id === playerId)
  if (!player) {
    throw new Error(`玩家${playerId}不存在`)
  }

  // 转换手牌为API格式ID（手牌不需要配牌处理）
  const handcards = convertCardsToAPIIds(player.handCards)

  // 构建历史出牌序列
  // 保留所有历史记录,包括已出完玩家的历史记录
  const card_play_action_seq: PlayActionItem[] = gameState.history.map(record => ({
    seatid: record.playerId,
    patterntype: mapCardPatternToAPIPattern(record.combination.type),
    // 直接传递原始牌值，不进行级牌配牌转换（后端自行处理配牌逻辑）
    cards: convertCardsToAPIIds(record.cards)
  }))

  // 获取级牌的rank值
  const mainface = gameState.config.trumpCard?.rank || 0

  // 判断是否是主动出牌（首次出牌或获得牌权）
  const fstplay = !gameState.lastPlay || gameState.lastPlayerId === playerId ? 1 : 0

  // 生成唯一的trace_id
  const trace_id = `${recordId}-${Date.now()}-${Math.random().toString(36).substring(2, 11)}`

  // 传递已出完玩家的ID数组
  const ranks = gameState.ranks || []

  console.log('构建出牌请求:', {
    playerId,
    ranks,
    historyCount: card_play_action_seq.length,
    handcardsCount: handcards.length
  })

  return {
    record_id: recordId,
    trace_id,
    position: 0,  // 首次出牌玩家的ID
    handcards,
    card_play_action_seq,
    mainface,
    ranks, // 传递已出完玩家的ID数组
    playtype: 1, // 经典玩法
    fstplay
  }
}

/**
 * 将内部牌型映射到API牌型
 */
function mapCardPatternToAPIPattern(pattern: CardPattern): number {
  // 根据API文档映射牌型
  // 0-过牌, 1-单, 2-对子, 3-刻子, 4-三带二, 5-木板, 6-钢板, 7-顺子, 8-四炸, 9-五炸, 10-同花顺, 11-六炸, 12-七炸, 13-八炸, 14-九炸, 15-十炸, 16-天王炸
  switch (pattern) {
    case CardPattern.PASS:
      return 0  // 过牌
    case CardPattern.SINGLE:
      return 1  // 单牌
    case CardPattern.PAIR:
      return 2  // 对子
    case CardPattern.TRIPLE:
      return 3  // 三张/刻子
    case CardPattern.TRIPLE_WITH_PAIR:
      return 4  // 三带二
    case CardPattern.WOOD_BOARD:
      return 5  // 木板
    case CardPattern.STEEL_BOARD:
      return 6  // 钢板
    case CardPattern.STRAIGHT:
      return 7  // 顺子
    case CardPattern.FOUR_BOMB:
      return 8  // 四炸
    case CardPattern.FIVE_BOMB:
      return 9  // 五炸
    case CardPattern.SAME_SUIT_STRAIGHT:
      return 10  // 同花顺
    case CardPattern.SIX_BOMB:
      return 11  // 六炸
    case CardPattern.SEVEN_BOMB:
      return 12  // 七炸
    case CardPattern.EIGHT_BOMB:
      return 13  // 八炸
    case CardPattern.NINE_BOMB:
      return 14  // 九炸
    case CardPattern.TEN_BOMB:
      return 15  // 十炸
    case CardPattern.KING_BOMB:
      return 16  // 天王炸
    default:
      return 0  // 默认返回过牌
  }
}

// 导出AI服务实例
export { aiService }
export default aiService